package com.zp.business.impl.patVisit;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.base.api.RemoteSerialNumberUtils;
import com.zp.business.entity.patVisit.PatVisit;
import com.zp.business.entity.patVisit.bo.PatVisitBo;
import com.zp.business.entity.patVisit.vo.PatVisitVo;
import com.zp.business.entity.patVisitIndex.PatVisitIndex;
import com.zp.business.entity.patVisitIndex.bo.PatVisitIndexBo;
import com.zp.business.entity.patVisitIndex.vo.PatVisitIndexVo;
import com.zp.business.mapper.patVisit.PatVisitMapper;
import com.zp.business.mapper.patVisitIndex.PatVisitIndexMapper;
import com.zp.business.service.patVisit.IPatVisitService;
import com.zp.common.core.constant.BaseConstants;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.constant.UserConstants;
import com.zp.common.core.utils.DateUtils;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.system.api.entity.SysDept;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 患者住院信息Service业务层处理
 *
 * @author zhang peng
 * @ date 2024-06-24
 */
@RequiredArgsConstructor
@Service
public class PatVisitServiceImpl implements IPatVisitService {

    static Map<String, SysDept> SYS_DEPT_MAP = CacheUtils.get(CacheNames.SYS_DEPT);
    private final PatVisitMapper baseMapper;
    private final PatVisitIndexMapper patVisitIndexMapper;
    @DubboReference
    private RemoteSerialNumberUtils remoteSerialNumberUtils;

    /**
     * 查询患者住院信息
     */
    @Override
    public PatVisitVo queryById(String visitId) {
        return baseMapper.selectVoById(visitId);
    }


    public List<PatVisitIndexVo> getPatVisitIndexList(PatVisitBo bo) {
        return patVisitIndexMapper.selectVoList(Wrappers.<PatVisitIndex>lambdaQuery()
                .eq(PatVisitIndex::getOrgId, bo.getOrgId())
                .eq(StringUtils.isNotBlank(bo.getName()), PatVisitIndex::getName, bo.getName())
        );
    }

    /**
     * 查询患者住院信息列表(分页)
     */
    @Override
    public TableDataInfo<PatVisitVo> queryPageList(PatVisitBo bo, PageQuery pageQuery) {
        Map<String, Object> params = bo.getParams();
        if (params.get("beginTime") != null && params.get("endTime") != null) {
            bo.setBeginTime(DateUtils.dateTime(params.get("beginTime")));
            bo.setEndTime(DateUtils.dateTime(params.get("endTime")));
        }
        Page<PatVisitVo> result = baseMapper.selectVoPage(pageQuery.build(), bo);
        result.getRecords().forEach(item -> {
            item.setDeptAdmissionToName(ObjectUtils.isNotEmpty(SYS_DEPT_MAP) && StringUtils.isNotBlank(item.getDeptAdmissionTo()) ?
                    SYS_DEPT_MAP.get(item.getDeptAdmissionTo()).getDeptName() : "");
            item.setWardAdmissionToName(ObjectUtils.isNotEmpty(SYS_DEPT_MAP) && StringUtils.isNotBlank(item.getWardAdmissionTo()) ?
                    SYS_DEPT_MAP.get(item.getWardAdmissionTo()).getDeptName() : "");
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询患者住院信息列表(不分页)
     */
    @Override
    public List<PatVisitVo> queryList(PatVisitBo bo) {
        LambdaQueryWrapper<PatVisit> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PatVisit> buildQueryWrapper(PatVisitBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PatVisit> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getPatientId()), PatVisit::getPatientId, bo.getPatientId());
        lqw.eq(StringUtils.isNotBlank(bo.getClinicId()), PatVisit::getClinicId, bo.getClinicId());
        lqw.eq(StringUtils.isNotBlank(bo.getHospitalNo()), PatVisit::getHospitalNo, bo.getHospitalNo());
        lqw.eq(bo.getHospitalizationNumber() != null, PatVisit::getHospitalizationNumber, bo.getHospitalizationNumber());
        lqw.eq(bo.getSituationTime() != null, PatVisit::getSituationTime, bo.getSituationTime());
        lqw.eq(StringUtils.isNotBlank(bo.getSituationType()), PatVisit::getSituationType, bo.getSituationType());
        lqw.eq(StringUtils.isNotBlank(bo.getHospitalSituation()), PatVisit::getHospitalSituation, bo.getHospitalSituation());
        lqw.eq(StringUtils.isNotBlank(bo.getQuarantine()), PatVisit::getQuarantine, bo.getQuarantine());
        lqw.eq(StringUtils.isNotBlank(bo.getDiagnosis()), PatVisit::getDiagnosis, bo.getDiagnosis());
        lqw.eq(StringUtils.isNotBlank(bo.getDiagnosisCode()), PatVisit::getDiagnosisCode, bo.getDiagnosisCode());
        lqw.eq(StringUtils.isNotBlank(bo.getDeptAdmissionTo()), PatVisit::getDeptAdmissionTo, bo.getDeptAdmissionTo());
        lqw.eq(StringUtils.isNotBlank(bo.getWardAdmissionTo()), PatVisit::getWardAdmissionTo, bo.getWardAdmissionTo());
        lqw.eq(bo.getAdmissionTime() != null, PatVisit::getAdmissionTime, bo.getAdmissionTime());
        lqw.eq(StringUtils.isNotBlank(bo.getChannel()), PatVisit::getChannel, bo.getChannel());
        lqw.eq(StringUtils.isNotBlank(bo.getSource()), PatVisit::getSource, bo.getSource());
        lqw.eq(StringUtils.isNotBlank(bo.getConfirmDoctor()), PatVisit::getConfirmDoctor, bo.getConfirmDoctor());
        lqw.eq(StringUtils.isNotBlank(bo.getWardDischargeTo()), PatVisit::getWardDischargeTo, bo.getWardDischargeTo());
        lqw.eq(StringUtils.isNotBlank(bo.getDeptDischargeTo()), PatVisit::getDeptDischargeTo, bo.getDeptDischargeTo());
        lqw.eq(bo.getDischargeTime() != null, PatVisit::getDischargeTime, bo.getDischargeTime());
        lqw.eq(StringUtils.isNotBlank(bo.getInFlag()), PatVisit::getInFlag, bo.getInFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getDeptFlag()), PatVisit::getDeptFlag, bo.getDeptFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getWardFlag()), PatVisit::getWardFlag, bo.getWardFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getDeptStayed()), PatVisit::getDeptStayed, bo.getDeptStayed());
        lqw.eq(StringUtils.isNotBlank(bo.getWardCode()), PatVisit::getWardCode, bo.getWardCode());
        lqw.eq(bo.getFirstEnterDeptTime() != null, PatVisit::getFirstEnterDeptTime, bo.getFirstEnterDeptTime());
        lqw.eq(bo.getEnterDeptTime() != null, PatVisit::getEnterDeptTime, bo.getEnterDeptTime());
        lqw.eq(bo.getFirstEnterWardTime() != null, PatVisit::getFirstEnterWardTime, bo.getFirstEnterWardTime());
        lqw.eq(bo.getEnterWardTime() != null, PatVisit::getEnterWardTime, bo.getEnterWardTime());
        lqw.eq(StringUtils.isNotBlank(bo.getQualityNurse()), PatVisit::getQualityNurse, bo.getQualityNurse());
        lqw.eq(StringUtils.isNotBlank(bo.getDutyNurse()), PatVisit::getDutyNurse, bo.getDutyNurse());
        lqw.eq(StringUtils.isNotBlank(bo.getDoctorInCharge()), PatVisit::getDoctorInCharge, bo.getDoctorInCharge());
        lqw.eq(StringUtils.isNotBlank(bo.getUpperDoctor()), PatVisit::getUpperDoctor, bo.getUpperDoctor());
        lqw.eq(StringUtils.isNotBlank(bo.getDirectorDoctor()), PatVisit::getDirectorDoctor, bo.getDirectorDoctor());
        lqw.eq(StringUtils.isNotBlank(bo.getNursingClass()), PatVisit::getNursingClass, bo.getNursingClass());
        lqw.eq(StringUtils.isNotBlank(bo.getFirstRoomNo()), PatVisit::getFirstRoomNo, bo.getFirstRoomNo());
        lqw.eq(bo.getFirstBedNo() != null, PatVisit::getFirstBedNo, bo.getFirstBedNo());
        lqw.eq(StringUtils.isNotBlank(bo.getFirstBedLabel()), PatVisit::getFirstBedLabel, bo.getFirstBedLabel());
        lqw.eq(StringUtils.isNotBlank(bo.getRoomNo()), PatVisit::getRoomNo, bo.getRoomNo());
        lqw.eq(StringUtils.isNotBlank(bo.getBedLabel()), PatVisit::getBedLabel, bo.getBedLabel());
        lqw.eq(StringUtils.isNotBlank(bo.getBedNo()), PatVisit::getBedNo, bo.getBedNo());
        lqw.eq(bo.getPrepayments() != null, PatVisit::getPrepayments, bo.getPrepayments());
        lqw.eq(bo.getPaymentInAdvance() != null, PatVisit::getPaymentInAdvance, bo.getPaymentInAdvance());
        lqw.eq(bo.getPaymentLast() != null, PatVisit::getPaymentLast, bo.getPaymentLast());
        lqw.eq(bo.getTotalCosts() != null, PatVisit::getTotalCosts, bo.getTotalCosts());
        lqw.eq(bo.getTotalCharges() != null, PatVisit::getTotalCharges, bo.getTotalCharges());
        lqw.eq(StringUtils.isNotBlank(bo.getSettledType()), PatVisit::getSettledType, bo.getSettledType());
        lqw.eq(StringUtils.isNotBlank(bo.getSettledIndicator()), PatVisit::getSettledIndicator, bo.getSettledIndicator());
        lqw.eq(bo.getHalfwayDate() != null, PatVisit::getHalfwayDate, bo.getHalfwayDate());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), PatVisit::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), PatVisit::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getLeaveWithoutNewborn()), PatVisit::getLeaveWithoutNewborn, bo.getLeaveWithoutNewborn());
        lqw.eq(StringUtils.isNotBlank(bo.getIsNewBornOutpHos()), PatVisit::getIsNewBornOutpHos, bo.getIsNewBornOutpHos());
        lqw.eq(StringUtils.isNotBlank(bo.getChanceDept()), PatVisit::getChanceDept, bo.getChanceDept());
        lqw.eq(bo.getQualityTime() != null, PatVisit::getQualityTime, bo.getQualityTime());
        lqw.eq(StringUtils.isNotBlank(bo.getMedicalQuality()), PatVisit::getMedicalQuality, bo.getMedicalQuality());
        lqw.eq(StringUtils.isNotBlank(bo.getLiveHosType()), PatVisit::getLiveHosType, bo.getLiveHosType());
        lqw.eq(StringUtils.isNotBlank(bo.getQualityDoctor()), PatVisit::getQualityDoctor, bo.getQualityDoctor());
        lqw.eq(bo.getLastAcctTime() != null, PatVisit::getLastAcctTime, bo.getLastAcctTime());
        lqw.eq(StringUtils.isNotBlank(bo.getFeesNo()), PatVisit::getFeesNo, bo.getFeesNo());
        return lqw;
    }

    /**
     * 新增患者住院信息
     */
    @Override
    public Boolean insertByBo(PatVisitBo bo) {
        PatVisit add = BeanUtil.toBean(bo, PatVisit.class);
        validEntityBeforeSave(add);
        add.initEntity();
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setVisitId(add.getVisitId());
        }
        return flag;
    }

    /**
     * 修改患者住院信息
     */
    @Override
    public Boolean updateByBo(PatVisitBo bo) {
        PatVisit update = BeanUtil.toBean(bo, PatVisit.class);
        update.updateInfo();
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PatVisit entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除患者住院信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 入院信息写入
     *
     * @param bo
     * @return
     */
    @Override
    public PatVisitVo insertByVo(PatVisitIndexBo bo) {
        PatVisit patVisit = BeanUtil.toBean(bo, PatVisit.class);
        List<PatVisitVo> patVisitVos = baseMapper.selectVoList(Wrappers.<PatVisit>lambdaQuery()
                .eq(PatVisit::getOrgId, bo.getOrgId())
                .eq(PatVisit::getPatientId, bo.getPatientId())
        );
        patVisit.setHospitalizationNumber(patVisitVos.size() + 1);
        patVisit.setHospitalNo(remoteSerialNumberUtils.generateHospitalNo(bo.getOrgId()));
        patVisit.setInFlag(BaseConstants.ENTRY_AND_EXIT_HOSPITAL_STATUS.ONE);
        patVisit.setWardFlag(UserConstants.NO);
        patVisit.setDeptFlag(UserConstants.NO);
        patVisit.initEntity();
        patVisit.setAdmissionTime(DateUtils.getNowDate());
        baseMapper.insert(patVisit);
        return BeanUtil.toBean(patVisit, PatVisitVo.class);
    }
}
